#pragma once

#include <iostream>
#include <memory>
#include "InetAddr.hpp"
#include "Epoller.hpp"
#include "Reactor.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Connection.hpp"
#include "IOService.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"

using namespace SocketModule;

// 专门负责获取连接的模块
// 连接管理器
class Listener : public Connection
{
public:
    Listener(int port)
        : _listensock(std::make_unique<TcpSocket>()),
          _port(port)
    {
        _listensock->BuildTcpSocketMethod(_port);
        SetSockfd(_listensock->Fd());
        SetEvents(EPOLLIN | EPOLLET);
    }
    virtual void Recver() override
    {
        // LOG(LogLevel::DEBUG) << "Get in Accepter Moduler.";
        // IO处理 -- 获取新连接
        // 如何得知一次来的连接数量有多少呢？要保证本次读完所有的连接
        while (true)
        {
            // 在accept 非阻塞的时候，就相当于IO；
            // 像处理read一样，处理accept
            InetAddr peer;
            int aerrno = 0;
            int sockfd = _listensock->Accepter(&peer, &aerrno);
            if (sockfd > 0)
            {
                // success
                // 此时listensockfd就绪意味着sockfd资源到位了
                // 但是sockfd资源到位不意味着读资源也就绪了
                // 因此是不能直接读取的
                // 需要将sockfd添加到epoll中
                // epoollserver只认connection
                //  auto conn = Factory::BuildConnection(sockfd, EPOLLIN | EPOLLET, nullptr, nullptr, nullptr);
                //  conn->SetPeerInfo(peer);
                //  conn->owner->InsertConnection();
                LOG(LogLevel::DEBUG) << "accepter success, sockfd is " << sockfd;
                // 此时为普通的文件描述符
                // //首先，由于我们使用的是ET模式，所以所有的fd都是要求非阻塞的。
                // SetNonBloack(sockfd);
                // //这个非阻塞设置在IOServer中更规整。

                //将sockfd包装Connection
                auto conn = std::make_shared<IOService>(sockfd);
                conn->RegisterOnMessage(HandlerRequest);
                //插入连接到EpollServer中
                GetOwner()->InsertConnection(conn);
            }
            else
            {
                if (aerrno == EAGAIN || aerrno == EWOULDBLOCK)
                {
                    LOG(LogLevel::DEBUG) << "accepter all connection...done";
                    break;
                }
                else if (aerrno == EINTR)
                {
                    LOG(LogLevel::DEBUG) << "accepter intr by signal,continue";
                    continue;
                    ;
                }
                else
                {
                    LOG(LogLevel::WARNING) << "accepter error...ignore";
                    break;
                }
            }
        }
    }
    virtual void Sender() override
    {
    }
    virtual void Excepter() override
    {
    }

    int Sockfd()
    {
        return _listensock->Fd();
    }
    ~Listener()
    {
        _listensock->Close();
    }

private:
    std::unique_ptr<Socket> _listensock;
    int _port;
};
